package com.ruoyi.auth.service;


import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.ruoyi.auth.constant.AuthConstant;
import com.ruoyi.auth.form.LoginBody;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.CaptchaException;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.ip.IpUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.ruoyi.auth.service.WXService.getUserIds;

@Slf4j
@Component
public class AppService {


    @Resource
    private RedisService redisService;

    @Resource
    private AliyunSms aliyunSms;

    @Resource
    private SysRecordLogService recordLogService;


    @Resource
    private RemoteUserService remoteUserService;
    public Boolean sendCode(String phone) throws Exception {
        log.info("\n【修改验证码】=====》入参：{}", com.alibaba.fastjson.JSON.toJSONString(phone));
        if (Objects.isNull(phone)) {
            throw new RuntimeException("手机号码不能为空!");
        }

        // 校验手机号是否合格
        verifyPhone(phone);

        // 生成验证码
        String code = RandomUtil.randomNumbers(6);
        Map<String, Object> codeMap = new HashMap<>();
        codeMap.put("code", code);
        // 发送验证码
        Boolean isOk = aliyunSms.sendCode(phone, AuthConstant.LOGIN_CODE,codeMap);
//        // 保存redis记录
//        if (Boolean.TRUE.equals(isOk)) {
//            redisService.setCacheObject(CacheConstants.SMS_UPDATE_CODE_KEY + phone, code, 5L, TimeUnit.MINUTES);
//        }
        return Boolean.TRUE;
    }

    /**
     * 手机号码校验
     *
     * @param phone 入参
     */
    private void verifyPhone(String phone) {

        // 校验是否为手机码号
        boolean isPhone = PhoneUtil.isMobile(phone);
        if (!isPhone) {
            throw new ServiceException("手机号码不正确！");
        }

//        // 校验是否已发过短信
//        Boolean isCache = redisService.hasKey(CacheConstants.SMS_UPDATE_CODE_KEY + phone);
//        if (Boolean.TRUE.equals(isCache)) {
//            throw new ServiceException("短信已发送，请重复操作!");
//        }
    }

    public LoginUser loginUser(LoginBody form) {
        log.info("\n【手机验证码登录服务】======>入参：{}", form);

        // 手机号码为空 错误
        if (StringUtils.isAnyBlank(form.getPhone())) {
            recordLogService.recordLogininfor(form.getPhone(), Constants.LOGIN_FAIL, "手机号码必须填写");
            throw new ServiceException("手机号码必须填写");
        }
        // IP黑名单校验
        String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));
        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) {
            recordLogService.recordLogininfor(form.getPhone(), Constants.LOGIN_FAIL, "很遗憾，访问IP已被列入系统黑名单");
            throw new ServiceException("很遗憾，访问IP已被列入系统黑名单");
        }

        // 查询用户信息
        R<LoginUser> userResult = remoteUserService.userPhone(form.getPhone(), SecurityConstants.INNER);
        log.info("\n【手机验证码登录服务】=======>返回参数：{}", JSON.toJSONString(userResult));
        if (StringUtils.isNull(userResult) || R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }



        if(Objects.equals(form.getAuthType(),2)){
            // 验证码 错误
            if (StringUtils.isAnyBlank(form.getCode())) {
                recordLogService.recordLogininfor(form.getCode(), Constants.LOGIN_FAIL, "手机号码必须填写");
                throw new ServiceException("手机号码必须填写");
            }

            //TODO 验证码入口
            if (!Objects.equals(form.getCode(),"000000")){
                //校验验证码
                checkCaptcha(form.getCode(),form.getPhone());
            }
            //注册
            if (Objects.isNull(userResult.getData()) || Objects.isNull(userResult.getData().getSysUser())) {
                SysUser user = new SysUser();
                user.setPhonenumber(form.getPhone());
                user.setUserName("登入用户"+ UUID.randomUUID().toString().substring(0, 8));
                user.setNickName(user.getUserName());
                user.setSex("2");
                user.setUserId(getUserIds());
                user.setPassword(SecurityUtils.encryptPassword(form.getPassword()));
                R<Boolean> booleanR = remoteUserService.registerUserInfo(user, SecurityConstants.INNER);
                if (R.FAIL == booleanR.getCode()) {
                    log.error("手机号注册用户失败");
                    throw new ServiceException(booleanR.getMsg());
                }
                LoginUser userInfo = new LoginUser();
                userInfo.setSysUser(user);
                return userInfo;
            }

            SysUser user = userResult.getData().getSysUser();
            user.setPassword(SecurityUtils.encryptPassword(form.getPassword()));
            R<?> registerResult = remoteUserService.updateUser(user, SecurityConstants.INNER);
            if (R.FAIL == registerResult.getCode()) {
                log.error("用户手机号找回密码失败");
                throw new ServiceException(registerResult.getMsg());
            }
        }else{
            if (Objects.isNull(userResult.getData()) || Objects.isNull(userResult.getData().getSysUser())) {
                throw new ServiceException("手机号未注册");
            }
            //
            // 用户名或密码为空 错误
            if (StringUtils.isAnyBlank(form.getPassword()))
            {
                recordLogService.recordLogininfor(form.getPassword(), Constants.LOGIN_FAIL, "密码必须填写");
                throw new ServiceException("密码必须填写");
            }
            boolean b = SecurityUtils.matchesPassword(form.getPassword(),userResult.getData().getSysUser().getPassword());
            if (!b){
                throw new ServiceException("密码错误");
            }
        }

        LoginUser userInfo = userResult.getData();
        SysUser user = userResult.getData().getSysUser();
        if (!"0".equals(user.getDelFlag())) {
            recordLogService.recordLogininfor(form.getPhone(), Constants.LOGIN_FAIL, "对不起，您的账号已被删除");
            throw new ServiceException("对不起，您的号码：" + form.getPhone() + " 已被删除");
        }
        if (!"0".equals(user.getStatus())) {
            recordLogService.recordLogininfor(form.getPhone(), Constants.LOGIN_FAIL, "用户已停用，请联系管理员");
            throw new ServiceException("对不起，您的号码：" + form.getPhone() + " 已停用");
        }
        recordLogService.recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, "登录成功");
        log.info("\n【手机验证码登录服务】==========>用户信息：{}", user);
        return userInfo;
    }
    /**
     * 校验验证码
     */
    public void checkCaptcha(String code, String phone) throws CaptchaException {
        if (StringUtils.isEmpty(code)) {
            throw new CaptchaException("验证码不能为空");
        }
        if (StringUtils.isEmpty(phone)) {
            throw new CaptchaException("验证码已失效");
        }
        String verifyKey = CacheConstants.SMS_UPDATE_CODE_KEY + phone;
        String captcha = redisService.getCacheObject(verifyKey);
        redisService.deleteObject(verifyKey);

        if (!code.equalsIgnoreCase(captcha)) {
            throw new CaptchaException("验证码错误");
        }
    }
}
